
import getData from './getData';
import EventClass from './Event';

export default class BaseModel extends EventClass {
    constructor(model) {
        super();

        // this.model = model;
        // 存储上一次已改变的值
        this.changed = {};
    }

    getType(data) {
        let type = Object.prototype.toString.call(data);

        type = type.slice(8, type.length - 1);

        return type;
    }

    set(args1, args2) {
        if (!this.changed) {
            this.changed = {};
        }
        if(args2 === undefined) {
            if(this.getType(args1) === 'Object') {
                Object.keys(args1)
                    .forEach((key) => {
                        let triggerKey = [];
                        // 此处区分下是a.b形势吗
                        if (key.includes('.') || key.includes('[')) {
                            const arr = key.split(/[\.\[]/);
                            let currentKey = '';
                            let currentObj = this.data;
                            let lastKey = arr.pop();
                            lastKey = lastKey.replace(']', '');

                            arr.forEach((item) => {
                                let isArray = false;

                                currentKey = item;
                                
                                if (currentKey.charAt(currentKey.length - 1) === ']') {
                                    isArray = true;
                                    currentKey = currentKey.substring(0, currentKey.length - 1);
                                }

                                if (typeof currentObj[currentKey] !== 'object') {
                                    currentObj[currentKey] = isArray ? [] : {};
                                }

                                triggerKey.push(currentKey);
                                currentObj = currentObj[currentKey];
                            });

                            currentObj[lastKey] = args1[key];
                        } else {
                            triggerKey = [key];
                            this.changed[key] = this.data[key];
                            this.data[key] = args1[key];
                        }

                        this.trigger(`change:${triggerKey.join('.')}`, args1);
                    });

                this.trigger('change', args1);
            }
            else {
                throw new Error('如果只传一个参数，必须传入一个对象');
            }
        }
        else {
            this.changed[args1] = this.data[args1];
            this.data[args1] = args2;
            this.trigger(`change:${args1}`, {
                [args1]: args2
            });
            this.trigger('change', {
                [args1]: args2
            });
        }
    }

    get(key) {
        if(typeof key === 'string') {
            return getData(this.data, key)
        }
        else if(this.getType(key) === 'Array') {
            let result = [];

            key.forEach((item) => {
                result.push(this.data[item]);
            });

            return result;
        }
        else {
            return this.data;
        }
    }

    has(attribute) {
        const {data} = this;

        if(data[attribute] === undefined || data[attribute] === null) {
            return false;
        }

        return true
    }

    // 深拷贝
    deepClone(data) {
        let copyData = null;

        if (/Number|String|Null|Function/.test(this.getType(data))) {
            return data;
        } else if (this.getType(data) === 'Array') {
            copyData = [];
            data.forEach((item) => {
                copyData.push(this.deepClone(item));
            });
        } else if (this.getType(data) === 'Object') {
            copyData = {};
            Object.keys(data)
                .forEach((key) => {
                    copyData[key] = this.deepClone(data[key]);
                });
        } else {
            copyData = this.data || this.deepClone(this.data);
        }

        return copyData;
    }

    // 获取上一次修改前的值
    previous(attribute) {
        let data = Object.assign({}, this.data, this.changed || {});

        if(attribute) {
            return data[attribute];
        }
        
        return data;
    }
}